#pragma once

#include "Common.h"

#define DECL_SINGLETON(klass)                 \
  public:                                     \
  static klass* Instance();                   \
  static klass& InstanceRef();

#define DECL_SINGLETON_DLL(klass)             \
  public:                                     \
  DLL_DECLARE static klass* Instance();       \
  DLL_DECLARE static klass& InstanceRef();

#if defined WIN32
#define IMPL_SINGLETON(klass)                 \
  klass* Singleton<klass>::__instance = 0;    \
  bool Singleton<klass>::__created_by_singleton = false;        \
  klass* klass::Instance(){ return Singleton<klass>::_instance(); };   \
  klass& klass::InstanceRef(){ return Singleton<klass>::_instanceRef(); }; 
#elif defined LINUX
#define IMPL_SINGLETON(klass)                                                \
  template<class klass> klass* Singleton<klass>::__instance = 0;             \
  template<class klass> bool Singleton<klass>::__created_by_singleton = false; \
  klass* klass::Instance(){ return Singleton<klass>::_instance(); };   \
  klass& klass::InstanceRef(){ return Singleton<klass>::_instanceRef(); }; 
#endif

namespace RayFrame
{
  /// Singleton class.
  template<typename T> 
  class DLL_DECLARE Singleton
  {
  private:
    static T*   __instance;
    static bool __created_by_singleton;
  protected:
    Singleton()
    {
      if( !__created_by_singleton )
        throw "Singleton cannot be created by subclass";
    }
  public:
    static T* _instance()
    {
      if( !__instance )
      {
        __created_by_singleton = true;
        try
        {
          __instance = new T;
        }
        catch (...)
        {
          __created_by_singleton = false;
        }
        __created_by_singleton = false;
      }
      return __instance;
    }

    static T& _instanceRef()
    {
      return (*_instance());
    }

  public:
    virtual ~Singleton()
    {
      printf("singleton destroying!");
    }
  };
};
